import type {
	UsePoptipParam,
} from './type';
import {
	shallowRef,
	onUnmounted,
	watch,
} from 'vue';
import {
	bindEvent,
	throttle,
} from '../../util';

export default function(
	{
		emitInput,
		emitShow,
		emitHide,
		showStatus,
		trigger,
		hideOnClick,
		interactive,
		disabled,
		appear,
	}:UsePoptipParam
){
	let initVisible=false;
	const referenceRef=shallowRef<HTMLElement>();
	const floatingRef=shallowRef<any>(null);
	const innerVisible=shallowRef<boolean>(false);
	const floatingExist=shallowRef<boolean>(false);
	//region 可见性
	const visible=(() => {
		if(disabled()){
			return false;
		}
		const showStatusVal=showStatus();
		if(showStatusVal==null){
			return innerVisible.value;
		}
		return showStatusVal;
	});
	//endregion
	//region 初始动画
	const appearFn=() => {
		return !initVisible||appear();
	};
	//endregion
	//region 触发监听器
	const referenceListenersFn=() => {
		const triggerVal=trigger();
		if(triggerVal==='hover'){
			return {
				mouseenter:_showTrigger,
				mouseleave:_hideTrigger,
			};
		}else if(triggerVal==='click'){
			return {
				click:_showTrigger,
			};
		}
		return null;
	};
	//endregion
	//region 显示/隐藏, 触发器
	function _showTrigger(){
		if(trigger()==='click'&&hideOnClick()){
			toggle();
		}else{
			show();
		}
	}
	function _hideTrigger(){
		if(trigger()==='hover'&&interactive()){
			startCheck();
		}else{
			hide();
		}
	}
	//endregion
	//region 显示/隐藏
	function show():void{
		toggle(true);
	}
	function hide():void{
		toggle(false);
	}
	function toggle(show?:boolean){
		if(disabled()){
			return;
		}
		_setVisible(show==null?!visible():show);
	}
	function _setVisible(show:boolean){
		if(innerVisible.value!==show){
			innerVisible.value=show;
		}
		if(showStatus()!==show){
			emitInput&&emitInput(show);
		}
	}
	//endregion
	//region 可交互范围检查
	const _checkInside=throttle((e:MouseEvent) => {
		if(floatingRef.value.isInside(e)){
			hide();
		}
	});
	const [
		onCheckInside,
		offCheckInside,
	]=bindEvent('mousemove',_checkInside,{
		passive:true,
	});
	function startCheck(){
		if(visible()){
			onCheckInside();
		}
	}
	function stopCheck(){
		_checkInside.pending()&&_checkInside.cancel();
		offCheckInside();
	}
	//endregion
	watch(visible,(visibleVal) => {
		stopCheck();
		if(visibleVal){
			initVisible=false;
			floatingExist.value=true;
			emitShow();
		}else{
			if(disabled()){
				_setVisible(false);
			}
			emitHide();
		}
	});
	if(visible()){
		initVisible=true;
		floatingExist.value=true;
	}
	onUnmounted(stopCheck);
	return {
		referenceRef,
		floatingRef,
		visible,
		appearFn,
		floatingExist,
		referenceListenersFn,
		mouseenterFn:stopCheck,
		mouseleaveFn(){
			if(trigger()==='hover'&&interactive()){
				startCheck();
			}
		},
		hiddenFn(){
			floatingExist.value=false;
		},
		show,
		hide,
		toggle,
	};
}